 1.ClickHouse MergeTree家族表引擎之ReplacingMergeTree
   
   这个引擎是在 MergeTree 的基础上，添加了“处理重复数据”的功能，该引擎和MergeTree的不同之处在于它会删除
具有相同主键的重复项。
   特点：
       1. 使用ORDER BY排序键作为判断重复的唯一键
       2. 数据的去重只会在合并的过程中触发
       3. 以数据分区为单位删除重复数据，不同分区的的重复数据不会被删除
       4. 找到重复数据的方式依赖数据已经ORDER BY排好序了
       5. 如果没有ver版本号，则保留重复数据的最后一行
       6. 如果设置了ver版本号，则保留重复数据中ver版本号最大的数据
   格式：
   ENGINE [=] ReplacingMergeTree(date-column [, sampling_expression], (primary, key), index_granularity, [ver])
   可以看出他比MergeTree只多了一个ver，这个ver指代版本列。
   案例：
create table replace_table(
id String,
code String,
create_time DateTime
)ENGINE=ReplacingMergeTree()
PARTITION BY toYYYYMM(create_time)
ORDER BY (id,code)
PRIMARY KEY id;

insert into replace_table values('A001','C1','2020-08-21 08:00:00');
insert into replace_table values('A001','C1','2020-08-22 08:00:00');
insert into replace_table values('A001','C8','2020-08-23 08:00:00');
insert into replace_table values('A001','C9','2020-08-24 08:00:00');
insert into replace_table values('A002','C2','2020-08-25 08:00:00');
insert into replace_table values('A003','C3','2020-08-26 08:00:00');

optimize强制触发：
SELECT *
FROM replace_table;

┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1 │ 2020-08-22 08:00:00 │
│ A001 │ C8 │ 2020-08-23 08:00:00 │
│ A001 │ C9 │ 2020-08-24 08:00:00 │
│ A002 │ C2 │ 2020-08-25 08:00:00 │
│ A003 │ C3 │ 2020-08-26 08:00:00 │
└──────┴──────┴─────────────────────┘   

   通过观察，去重是根据ORDER BY来的，并非PRIMARY KEY
   在继续插入一条数据：
insert into replace_table values('A001','C1','2020-05-21 08:00:00');

linux121 :) OPTIMIZE TABLE replace_table;

OPTIMIZE TABLE replace_table

Ok.

0 rows in set. Elapsed: 0.003 sec. 

linux121 :) select * from replace_table;

SELECT *
FROM replace_table

┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2020-05-21 08:00:00 │
└──────┴──────┴─────────────────────┘
┌─id───┬─code─┬─────────create_time─┐
│ A001 │ C1   │ 2020-08-22 08:00:00 │
│ A001 │ C8   │ 2020-08-23 08:00:00 │
│ A001 │ C9   │ 2020-08-24 08:00:00 │
│ A002 │ C2   │ 2020-08-25 08:00:00 │
│ A003 │ C3   │ 2020-08-26 08:00:00 │
└──────┴──────┴─────────────────────┘

 2.SummingMergeTree
   
   该引擎继承自 MergeTree。区别在于，当合并 SummingMergeTree 表的数据片段时，ClickHouse 会把所有具有相
同聚合数据的条件Key的行合并为一行，该行包含了被合并的行中具有数值数据类型的列的汇总值。如果聚合数据的
条件Key的组合方式使得单个键值对应于大量的行，则可以显著的减少存储空间并加快数据查询的速度，对于不可加
的列，会取一个最先出现的值。
   特征：
       1. 用ORDER BY排序键作为聚合数据的条件Key
       2. 合并分区的时候触发汇总逻辑
       3. 以数据分区为单位聚合数据，不同分区的数据不会被汇总
       4. 如果在定义引擎时指定了Columns汇总列（非主键）则SUM汇总这些字段
       5. 如果没有指定，则汇总所有非主键的数值类型字段
       6. SUM汇总相同的聚合Key的数据，依赖ORDER BY排序
       7. 同一分区的SUM汇总过程中，非汇总字段的数据保留第一行取值
       8. 支持嵌套结构，但列字段名称必须以Map后缀结束。
   语法：
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE = SummingMergeTree([columns])
[PARTITION BY expr]
[ORDER BY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]

   columns — 包含将要被汇总的列的列名的元组
   案例1： 
create table smt_table (date Date, name String, a UInt16, b UInt16)
ENGINE=SummingMergeTree(date, (date, name), 8192, (a));
   插入数据：
insert into smt_table (date, name, a, b) values ('2019-07-10', 'a', 1, 2);
insert into smt_table (date, name, a, b) values ('2019-07-10', 'b', 2, 1);
insert into smt_table (date, name, a, b) values ('2019-07-11', 'b', 3, 8);
insert into smt_table (date, name, a, b) values ('2019-07-11', 'b', 3, 8);
insert into smt_table (date, name, a, b) values ('2019-07-11', 'a', 3, 1);
insert into smt_table (date, name, a, b) values ('2019-07-12', 'c', 1, 3);
   等待一段时间或optimize table smt_table手动触发merge，后查询
linux121 :) select * from smt_table
:-] ;

SELECT *
FROM smt_table

┌───────date─┬─name─┬─a─┬─b─┐
│ 2019-07-10 │ a    │ 1 │ 2 │
│ 2019-07-10 │ b    │ 2 │ 1 │
│ 2019-07-11 │ a    │ 3 │ 1 │
│ 2019-07-11 │ b    │ 6 │ 8 │
│ 2019-07-12 │ c    │ 1 │ 3 │
└────────────┴──────┴───┴───┘
   
   发现2019-07-11,b的a列合并相加了，b列取了8（因为b列为8的数据最先插入）。
   案例2：
create table summing_table(
id String,
city String,
v1 UInt32,
v2 Float64,
create_time DateTime
)ENGINE=SummingMergeTree()
PARTITION BY toYYYYMM(create_time)
ORDER BY (id,city)
PRIMARY KEY id;

insert into table summing_table values('A000','beijing',10,20,'2020-08-20 08:00:00');
insert into table summing_table values('A000','beijing',20,30,'2020-08-30 08:00:00');
insert into table summing_table values('A000','shanghai',10,20,'2020-08-20 08:00:00');
insert into table summing_table values('A000','beijing',10,20,'2020-06-20 08:00:00');
insert into table summing_table values('A001','beijing',50,60,'2020-02-20 08:00:00');

linux121 :) OPTIMIZE TABLE summing_table;

OPTIMIZE TABLE summing_table

Ok.

0 rows in set. Elapsed: 0.010 sec. 

linux121 :) select * from summing_table;

SELECT *
FROM summing_table

┌─id───┬─city────┬─v1─┬─v2─┬─────────create_time─┐
│ A001 │ beijing │ 50 │ 60 │ 2020-02-20 08:00:00 │
└──────┴─────────┴────┴────┴─────────────────────┘
┌─id───┬─city────┬─v1─┬─v2─┬─────────create_time─┐
│ A000 │ beijing │ 10 │ 20 │ 2020-06-20 08:00:00 │
└──────┴─────────┴────┴────┴─────────────────────┘
┌─id───┬─city─────┬─v1─┬─v2─┬─────────create_time─┐
│ A000 │ beijing  │ 30 │ 50 │ 2020-08-20 08:00:00 │
│ A000 │ shanghai │ 10 │ 20 │ 2020-08-20 08:00:00 │
└──────┴──────────┴────┴────┴─────────────────────┘

   通过观察，根据ORDER BY排序键(id,city)作为聚合Key,因为没有在建表指定SummingMergeTree的时候没有指定
Sum列，所以把所有非主键数值类型的列都进行了SUM逻辑
┌─id───┬─city────┬─v1─┬─v2─┬─────────create_time─┐
│ A000 │ beijing │ 20 │ 30 │ 2020-08-30 08:00:00 │
└──────┴─────────┴────┴────┴─────────────────────┘
┌─id───┬─city─────┬─v1─┬─v2─┬─────────create_time─┐
│ A000 │ shanghai │ 10 │ 20 │ 2020-08-20 08:00:00 │
└──────┴──────────┴────┴────┴─────────────────────┘

   这两条数据v1和v2分别相加SUM后结果为30,50
┌─id───┬─city─────┬─v1─┬─v2─┬─────────create_time─┐
│ A000 │ beijing │ 30 │ 50 │ 2020-08-20 08:00:00 │
│ A000 │ shanghai │ 10 │ 20 │ 2020-08-20 08:00:00 │
└──────┴──────────┴────┴────┴─────────────────────┘

   案例3：
   SummingMergeTree支持嵌套类型的字段，但列字段名称必须以Map后缀结束。 
create table summing_table_nested(
id String,
nestMap Nested(
id UInt32,
key UInt32,
val UInt64
),
create_time DateTime
)ENGINE=SummingMergeTree()
PARTITION BY toYYYYMM(create_time)
ORDER BY id;

id:A001
nestMap.id: [1,1,2]
nestMap.key[10,20,100]
nestMap.val[40,60,20]
create_time: 2020-08-22 08:00:00

   [(1, 10, 40)] + [(1, 20, 60)] -> [(1, 30, 100)]
[(2, 100, 20)] -> [(2, 100, 20)]      

 3.AggregateMergeTree
   
   说明： 该引擎继承自 MergeTree，并改变了数据片段的合并逻辑。 ClickHouse 会将相同主键的所有行（在一个数据
片段内）替换为单个存储一系列聚合函数状态的行。 可以使用 AggregatingMergeTree 表来做增量数据统计聚合，包括
物化视图的数据聚合。 引擎需使用 AggregateFunction 类型来处理所有列。如果要按一组规则来合并减少行数，则使用
AggregatingMergeTree 是合适的。对于AggregatingMergeTree不能直接使用insert来查询写入数据。一般是用 insert 
select。但更常用的是创建物化视图
   a. 先创建一个MergeTree引擎的基表
linux121 :) create table arr_table_base (id String, city String, code String,value UInt32)
:-] engine=MergeTree partition by city order by (id,city);

CREATE TABLE arr_table_base
(
    `id` String,
    `city` String,
    `code` String,
    `value` UInt32
)
ENGINE = MergeTree
PARTITION BY city
ORDER BY (id, city)
   
   b. 往基表写入数据
   c. 创建一个AggregatingMergeTree的物化视图
linux121 :) create materialized view agg_view engine=AggregatingMergeTree() partition by city order
by(id,city) as select id,city,uniqState(code) as code, sumState(value) as value from
arr_table_base group by id,city;

CREATE MATERIALIZED VIEW agg_view
ENGINE = AggregatingMergeTree()
PARTITION BY city
ORDER BY (id, city) AS
SELECT 
    id,
    city,
    uniqState(code) AS code,
    sumState(value) AS value
FROM arr_table_base
GROUP BY 
    id,
    city
   
   d. 根据b往基表写数据的方法重写写一次将数据填充到物化视图amt_tab_view中并查询
insert into table arr_table_base values
('A000','wuhan','code1',1),
('A000','wuhan','code2',200),
('A000','zhuhai','code1',200);
   e. 通过optimize命令手动Merge后查询
linux121 :) select id,sumMerge(value),uniqMerge(code) from agg_view group by id,city;

SELECT 
    id,
    sumMerge(value),
    uniqMerge(code)
FROM agg_view
GROUP BY 
    id,
    city

┌─id───┬─sumMerge(value)─┬─uniqMerge(code)─┐
│ A000 │             200 │               1 │
│ A000 │             201 │               2 │
└──────┴─────────────────┴─────────────────┘

   f. 使用场景
   可以使用AggregatingMergeTree表来做增量数据统计聚合，包括物化视图的数据聚合。

 4.CollapsingMergeTree
   
   以增代删： 
   说明： yandex官方给出的介绍是CollapsingMergeTree 会异步的删除（折叠）这些除了特定列 Sign 有 1 和 -1 的值
以外，其余所有字段的值都相等的成对的行。没有成对的行会被保留.该引擎可以显著的降低存储量并提高 SELECT查询效
率。 CollapsingMergeTree引擎有个状态列sign，这个值1为”状态”行，-1 为"取消"行，对于数据只关心状态列为状态的
数据，不关心状态列为取消的数据.
   a. 创建CollapsingMergeTree表
   创表语法： 
CREATE TABLE cmt_tab(
sign Int8,
date Date,
name String,
point String) ENGINE=CollapsingMergeTree(sign)
PARTITION BY date
ORDER BY (name)
SAMPLE BY name;

CREATE TABLE cmt_tab
(
    `sign` Int8,
    `date` Date,
    `name` String,
    `point` String
)
ENGINE = CollapsingMergeTree(sign)
PARTITION BY date
ORDER BY name
SAMPLE BY name

   b. 插入数据：
insert into cmt_tab(sign,date,name,point) values (1,'2019-12-13','cctv','100000');
insert into cmt_tab(sign,date,name,point) values (-1,'2019-12-13','cctv','100000');
insert into cmt_tab(sign,date,name,point) values (1,'2019-12-13','hntv','10000');
insert into cmt_tab(sign,date,name,point) values (-1,'2019-12-13','hntv','10000');
insert into cmt_tab(sign,date,name,point) values (1,'2019-12-13','hbtv','11000');
insert into cmt_tab(sign,date,name,point) values (-1,'2019-12-13','hbtv','11000');
insert into cmt_tab(sign,date,name,point) values (1,'2019-12-14','cctv','200000');
insert into cmt_tab(sign,date,name,point) values (1,'2019-12-14','hntv','15000');
insert into cmt_tab(sign,date,name,point) values (1,'2019-12-14','hbtv','16000');

   c. 通过optimize table amt_tab_view命令手动Merge后查询
SELECT *
FROM cmt_tab;

┌─sign─┬───────date─┬─name─┬─point──┐
│    1 │ 2019-12-14 │ cctv │ 200000 │
└──────┴────────────┴──────┴────────┘
┌─sign─┬───────date─┬─name─┬─point─┐
│    1 │ 2019-12-14 │ hntv │ 15000 │
└──────┴────────────┴──────┴───────┘
┌─sign─┬───────date─┬─name─┬─point─┐
│    1 │ 2019-12-14 │ hbtv │ 16000 │
└──────┴────────────┴──────┴───────┘
   
   d.使用场景
   大数据中对于数据更新很难做到，比如统计一个网站或TV的在用户数，更多场景都是选择用记录每个点的数据，再对
数据进行一定聚合查询。而clickhouse通过CollapsingMergeTree就可以实现，所以使得CollapsingMergeTree大部分用于
OLAP场景   

 5.VersionedCollapsingMergeTree
   
   这个引擎和CollapsingMergeTree差不多，只是对CollapsingMergeTree引擎加了一个版本，比如可以适用于非实时
用户在线统计，统计每个节点用户在在线业务 a. 创表语法
   

